package com.learn.algorithm_may_1;

/**
 * 三个不同的线程将会共用一个 Foo 实例。
 *
 * 线程 A 将会调用 one() 方法
 * 线程 B 将会调用 two() 方法
 * 线程 C 将会调用 three() 方法
 * 请设计修改程序，以确保 two() 方法在 one() 方法之后被执行，three() 方法在 two() 方法之后被执行。
 *
 * 1114，https://leetcode-cn.com/problems/print-in-order/
 *
 */
class Foo {

    private boolean firstFinished = false;
    private boolean secondFinished = false;

    private Object lock = new Object();

    public Foo() {

    }

    public void first(Runnable printFirst) throws InterruptedException {
        synchronized (lock){
            printFirst.run();
            firstFinished = true;
            lock.notifyAll();
        }
    }

    public void second(Runnable printSecond) throws InterruptedException {
        synchronized (lock){
            while (!firstFinished){
                //- 释放锁
                lock.wait();
            }
            printSecond.run();
            secondFinished = true;
            //- 唤醒其他等待该锁的线程
            lock.notifyAll();
        }
    }

    public void third(Runnable printThird) throws InterruptedException {
        synchronized (lock){
            while (!secondFinished){
                //- 释放锁
                lock.wait();
            }
            printThird.run();
        }
    }
}